<template>
    <div class="steps-container">
        <!-- 步骤条 -->
        <el-steps :active="currentStep" :direction="direction" :align-center="alignCenter"
            :process-status="processStatus" :finish-status="finishStatus" :space="space" :simple="simple"
            class="steps-nav">
            <el-step v-for="(step, index) in steps" :key="index" :title="step.title" :description="step.description"
                :icon="step.icon" :status="getStepStatus(index)" />
        </el-steps>

        <!-- 步骤内容 -->
        <div class="steps-content">
            <transition :name="transitionName" mode="out-in">
                <div :key="currentStep" class="step-content">
                    <!-- 表单步骤 -->
                    <DynamicForm v-if="currentStepConfig.type === 'form'" ref="formRef" v-model="formData"
                        :config="currentStepConfig.formConfig" :label-width="formLabelWidth"
                        :label-position="formLabelPosition" :size="formSize" :show-buttons="false"
                        @submit="handleStepSubmit" />

                    <!-- 自定义内容 -->
                    <div v-else-if="currentStepConfig.type === 'custom'" class="custom-content">
                        <slot :name="`step-${currentStep}`" :data="stepData[currentStep]" :form-data="formData" />
                    </div>

                    <!-- 确认步骤 -->
                    <div v-else-if="currentStepConfig.type === 'confirm'" class="confirm-content">
                        <div class="confirm-title">{{ currentStepConfig.title }}</div>
                        <div v-if="currentStepConfig.description" class="confirm-description">
                            {{ currentStepConfig.description }}
                        </div>

                        <!-- 表单数据预览 -->
                        <div v-if="showFormPreview" class="form-preview">
                            <div v-for="(step, stepIndex) in steps" :key="stepIndex" class="step-preview">
                                <div v-if="step.type === 'form' && stepData[stepIndex]" class="step-data">
                                    <div class="step-data-title">{{ step.title }}</div>
                                    <div class="step-data-content">
                                        <div v-for="(field, fieldIndex) in getPreviewFields(step.formConfig, stepData[stepIndex])"
                                            :key="fieldIndex" class="field-item">
                                            <span class="field-label">{{ field.label }}：</span>
                                            <span class="field-value">{{ field.value }}</span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- 自定义确认内容 -->
                        <slot v-else name="confirm" :data="stepData" :form-data="formData" />
                    </div>

                    <!-- 结果步骤 -->
                    <div v-else-if="currentStepConfig.type === 'result'" class="result-content">
                        <div class="result-icon">
                            <el-icon v-if="resultType === 'success'" class="success-icon">
                                <SuccessFilled />
                            </el-icon>
                            <el-icon v-else-if="resultType === 'error'" class="error-icon">
                                <CircleCloseFilled />
                            </el-icon>
                            <el-icon v-else class="info-icon">
                                <InfoFilled />
                            </el-icon>
                        </div>
                        <div class="result-title">{{ resultTitle || currentStepConfig.title }}</div>
                        <div v-if="resultMessage" class="result-message">{{ resultMessage }}</div>

                        <!-- 自定义结果内容 -->
                        <slot name="result" :data="stepData" :form-data="formData" />
                    </div>
                </div>
            </transition>
        </div>

        <!-- 操作按钮 -->
        <div class="steps-actions">
            <slot name="actions" :current-step="currentStep" :is-first="isFirstStep" :is-last="isLastStep">
                <el-button v-if="!isFirstStep" @click="prevStep">
                    {{ prevButtonText }}
                </el-button>
                <el-button v-if="!isLastStep" type="primary" :loading="loading" @click="nextStep">
                    {{ nextButtonText }}
                </el-button>
                <el-button v-else type="primary" :loading="loading" @click="submitSteps">
                    {{ submitButtonText }}
                </el-button>
            </slot>
        </div>
    </div>
</template>

<script setup lang="ts">
/**
 * 步骤条组件
 * @author Wu.Liang
 * @description 支持多步骤表单、向导等场景
 */
import { ref, reactive, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { SuccessFilled, CircleCloseFilled, InfoFilled } from '@element-plus/icons-vue'
import DynamicForm from './DynamicForm.vue'
import type { FormItemConfig } from './DynamicForm.vue'
import { showSuccess, showError, showWarning, showInfo } from '@/utils/message'

interface StepConfig {
    // 步骤标题
    title: string
    // 步骤描述
    description?: string
    // 步骤图标
    icon?: any
    // 步骤类型
    type: 'form' | 'custom' | 'confirm' | 'result'
    // 表单配置（type为form时）
    formConfig?: FormItemConfig[]
    // 是否必填（表单步骤）
    required?: boolean
    // 验证函数
    validator?: (data: any) => Promise<boolean> | boolean
}

interface Props {
    // 步骤配置
    steps: StepConfig[]
    // 当前步骤
    modelValue?: number
    // 方向
    direction?: 'horizontal' | 'vertical'
    // 是否居中对齐
    alignCenter?: boolean
    // 进行中状态
    processStatus?: 'wait' | 'process' | 'finish' | 'error' | 'success'
    // 完成状态
    finishStatus?: 'wait' | 'process' | 'finish' | 'error' | 'success'
    // 步骤间距
    space?: string | number
    // 简洁模式
    simple?: boolean
    // 过渡动画
    transitionName?: string
    // 表单配置
    formLabelWidth?: string
    formLabelPosition?: 'left' | 'right' | 'top'
    formSize?: 'large' | 'default' | 'small'
    // 是否显示表单预览（确认步骤）
    showFormPreview?: boolean
    // 按钮文本
    prevButtonText?: string
    nextButtonText?: string
    submitButtonText?: string
    // 加载状态
    loading?: boolean
    // 结果配置
    resultType?: 'success' | 'error' | 'info'
    resultTitle?: string
    resultMessage?: string
}

const props = withDefaults(defineProps<Props>(), {
    modelValue: 0,
    direction: 'horizontal',
    alignCenter: false,
    processStatus: 'process',
    finishStatus: 'finish',
    simple: false,
    transitionName: 'fade',
    formLabelWidth: '100px',
    formLabelPosition: 'right',
    formSize: 'default',
    showFormPreview: true,
    prevButtonText: '上一步',
    nextButtonText: '下一步',
    submitButtonText: '提交',
    loading: false,
    resultType: 'success'
})

const emit = defineEmits<{
    'update:modelValue': [step: number]
    'step-change': [currentStep: number, prevStep: number]
    'step-submit': [stepIndex: number, data: any]
    'before-step': [currentStep: number, nextStep: number]
    'submit': [data: Record<number, any>]
}>()

const formRef = ref()
const formData = ref<Record<string, any>>({})
const stepData = reactive<Record<number, any>>({})

// 计算属性
const currentStep = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
})

const currentStepConfig = computed(() => {
    return props.steps[currentStep.value] || {}
})

const isFirstStep = computed(() => currentStep.value === 0)
const isLastStep = computed(() => currentStep.value === props.steps.length - 1)

// 监听步骤变化
watch(currentStep, (newStep, oldStep) => {
    // 重置表单数据
    if (currentStepConfig.value.type === 'form') {
        formData.value = stepData[newStep] || {}
    }

    emit('step-change', newStep, oldStep)
})

// 获取步骤状态
const getStepStatus = (index: number) => {
    if (index < currentStep.value) {
        return props.finishStatus
    } else if (index === currentStep.value) {
        return props.processStatus
    } else {
        return 'wait'
    }
}

// 获取预览字段
const getPreviewFields = (formConfig?: FormItemConfig[], data?: any) => {
    if (!formConfig || !data) return []

    return formConfig
        .filter(item => item.prop && item.type !== 'group')
        .map(item => ({
            label: item.label,
            value: formatPreviewValue(data[item.prop!], item)
        }))
}

// 格式化预览值
const formatPreviewValue = (value: any, config: FormItemConfig) => {
    if (value === null || value === undefined || value === '') return '-'

    // 根据字段类型格式化
    switch (config.type) {
    case 'select':
    case 'radio':
        const option = config.options?.find(opt => opt.value === value)
        return option ? option.label : value
    case 'checkbox':
        if (Array.isArray(value)) {
            return value
                .map(v => config.options?.find(opt => opt.value === v)?.label || v)
                .join(', ')
        }
        return value
    case 'switch':
        return value ? '是' : '否'
    case 'date':
    case 'datetime':
        return value
    default:
        return value
    }
}

// 步骤操作
const nextStep = async() => {
    // 验证当前步骤
    if (!(await validateCurrentStep())) {
        return
    }

    // 触发步骤切换前事件
    emit('before-step', currentStep.value, currentStep.value + 1)

    // 保存当前步骤数据
    if (currentStepConfig.value.type === 'form') {
        stepData[currentStep.value] = { ...formData.value }
        emit('step-submit', currentStep.value, formData.value)
    }

    // 切换到下一步
    if (!isLastStep.value) {
        currentStep.value++
    }
}

const prevStep = () => {
    if (!isFirstStep.value) {
        currentStep.value--
    }
}

const validateCurrentStep = async(): Promise<boolean> => {
    const stepConfig = currentStepConfig.value

    // 表单验证
    if (stepConfig.type === 'form') {
        if (formRef.value) {
            try {
                await formRef.value.validate()
            } catch (error) {
                showWarning('请检查表单填写是否正确')
                return false
            }
        }

        // 自定义验证
        if (stepConfig.validator) {
            try {
                const isValid = await stepConfig.validator(formData.value)
                if (!isValid) {
                    showWarning('当前步骤验证失败')
                    return false
                }
            } catch (error) {
                showError('步骤验证出错')
                return false
            }
        }
    }

    return true
}

const handleStepSubmit = (data: Record<string, any>) => {
    formData.value = data
}

const submitSteps = async() => {
    // 验证当前步骤
    if (!(await validateCurrentStep())) {
        return
    }

    // 保存最后一步数据
    if (currentStepConfig.value.type === 'form') {
        stepData[currentStep.value] = { ...formData.value }
    }

    // 提交所有步骤数据
    emit('submit', stepData)
}

// 跳转到指定步骤
const goToStep = (stepIndex: number) => {
    if (stepIndex >= 0 && stepIndex < props.steps.length) {
        currentStep.value = stepIndex
    }
}

// 重置步骤
const resetSteps = () => {
    currentStep.value = 0
    Object.keys(stepData).forEach(key => {
        delete stepData[Number(key)]
    })
    formData.value = {}
}

// 暴露方法
defineExpose({
    goToStep,
    resetSteps,
    validateCurrentStep,
    stepData,
    formData
})
</script>

<style lang="scss" scoped>
.steps-container {
    .steps-nav {
        margin-bottom: 30px;
    }

    .steps-content {
        min-height: 300px;
        margin-bottom: 30px;

        .step-content {
            .confirm-content {
                .confirm-title {
                    font-size: 18px;
                    font-weight: 600;
                    color: var(--el-text-color-primary);
                    margin-bottom: 10px;
                }

                .confirm-description {
                    font-size: 14px;
                    color: var(--el-text-color-regular);
                    margin-bottom: 20px;
                }

                .form-preview {
                    .step-preview {
                        margin-bottom: 20px;

                        .step-data {
                            border: 1px solid var(--el-border-color-light);
                            border-radius: 6px;
                            padding: 16px;

                            .step-data-title {
                                font-size: 16px;
                                font-weight: 600;
                                color: var(--el-text-color-primary);
                                margin-bottom: 12px;
                                padding-bottom: 8px;
                                border-bottom: 1px solid var(--el-border-color-lighter);
                            }

                            .step-data-content {
                                .field-item {
                                    display: flex;
                                    margin-bottom: 8px;

                                    &:last-child {
                                        margin-bottom: 0;
                                    }

                                    .field-label {
                                        width: 120px;
                                        flex-shrink: 0;
                                        color: var(--el-text-color-secondary);
                                        font-size: 14px;
                                    }

                                    .field-value {
                                        flex: 1;
                                        color: var(--el-text-color-primary);
                                        font-size: 14px;
                                        word-break: break-all;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            .result-content {
                text-align: center;
                padding: 40px 20px;

                .result-icon {
                    margin-bottom: 20px;

                    .success-icon {
                        color: var(--el-color-success);
                        font-size: 64px;
                    }

                    .error-icon {
                        color: var(--el-color-danger);
                        font-size: 64px;
                    }

                    .info-icon {
                        color: var(--el-color-info);
                        font-size: 64px;
                    }
                }

                .result-title {
                    font-size: 24px;
                    font-weight: 600;
                    color: var(--el-text-color-primary);
                    margin-bottom: 12px;
                }

                .result-message {
                    font-size: 16px;
                    color: var(--el-text-color-regular);
                    line-height: 1.6;
                }
            }
        }
    }

    .steps-actions {
        display: flex;
        justify-content: center;
        gap: 16px;
    }
}

// 过渡动画
.fade-enter-active,
.fade-leave-active {
    transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
    opacity: 0;
}

.slide-enter-active,
.slide-leave-active {
    transition: transform 0.3s ease;
}

.slide-enter-from {
    transform: translateX(100%);
}

.slide-leave-to {
    transform: translateX(-100%);
}
</style>
